import type { RequestConfig, RunTimeLayoutConfig } from "@umijs/max";
import { history } from "@umijs/max";
import { AvatarDropdown, AvatarName } from "@/components";
import defaultSettings, { apiUrl } from "../config/defaultSettings";
import "@ant-design/v5-patch-for-react-19";
import { message, Radio, Spin } from "antd";
import { UserOutlined, SunFilled, MoonFilled } from "@ant-design/icons";
import { useState, createElement, lazy, Suspense } from "react";
import * as allIcons from "@ant-design/icons";
import type { TYPE } from "./pages/types";
import storage from "./utils/storage";
import { decode } from "./utils/encrypt";

/**
 * 用户登录的路由
 */
const loginPath = "/user/login";

/**
 * 根据当前"path"获取对应的"name"。
 */
const mappingPath: any = {
  "welcomeYou": "首页",
};

// @see https://umijs.org/docs/api/runtime-config#getinitialstate
export const getInitialState = () => {
  // 浏览器刷新后，从缓存里获取数据。
  const { token, user, route, accessData } = storage.getData();
  const initialState: TYPE.InitialState = {
    loading: false, token, user, accessData,
  };
  const { pathname } = history.location;
  const { oldRender } = storage;

  if (pathname !== loginPath && route.length && !routeData.length && oldRender)
    render(oldRender, route); // 重新渲染路由
  return initialState;
};

// ProLayout 支持的api https://procomponents.ant.design/components/layout
export const layout: RunTimeLayoutConfig = ({ initialState }) => {
  const { Group, Button } = Radio;
  const [navTheme, navThemeSet] = useState(defaultSettings.navTheme);

  return {
    ...defaultSettings,
    logo: <img alt="logo" src="/logo.png" />,
    pageTitleRender: (props: any) => {
      const { pathname } = props.location;
      return mappingPath[pathname.substring(1)] || "";
    },
    // 右上角小图标按钮
    actionsRender: () => [
      // 切换黑白主题
      <Group
        size="small"
        buttonStyle="solid"
        defaultValue={defaultSettings.navTheme}
        onChange={e => navThemeSet(e.target.value)}
      >
        <Button value="light"><SunFilled /></Button>
        <Button value="realDark"><MoonFilled /></Button>
      </Group>,
    ],
    // 右上角用户名
    avatarProps: {
      title: <AvatarName />,
      icon: <UserOutlined />,
      style: {
        backgroundColor: "unset",
        border: "1px solid",
        color: "var(--ant-color-text)",
      },
      render: (_, child) => <AvatarDropdown>{child}</AvatarDropdown>,
    },
    onPageChange: location => {
      if (location?.pathname !== loginPath) {
        if (initialState?.token.length !== 14) {
          // 若没有登录，则跳转到登录页。
          history.replace({ pathname: loginPath });
        }
      }
    },
    childrenRender: content => {
      return (
        <Spin size="large" spinning={initialState?.loading}>
          {content}
        </Spin>
      );
    },
    contentStyle: { padding: 0 }, // 不需要内边距，让屏幕占用率更大一些。
    navTheme,
  };
};

/**
 * 动态路由数据，在登录时传入。
 */
let routeData: TYPE.RouteItem[] = [];
/**
 * @name 运行时添加路由(路由懒加载)
 * @description 此函数的触发条件是执行 oldRender()
 * @doc https://umijs.org/docs/api/runtime-config#patchclientroutes
 */
export const patchClientRoutes = (e: any) => {
  const routes = e.routes as TYPE.RouteItem[];
  for (let i = 0; i < routes.length; i += 1) {
    const routeItem = routes[i];
    const { id, children = [] } = routeItem;
    if (id !== "ant-design-pro-layout") continue;

    if (children.length <= 2) {
      // 在这里添加路由是带布局的，加长度判断是防止重复添加。
      children.push(...routeData);
      break;
    }
  }
};
/**
 * 当此函数被调用时，会自动执行 patchClientRoutes函数。
 */
export const render = (oldRender: Function, newRoute: TYPE.RouteItem[] = []) => {
  storage.oldRender = oldRender;
  const icons = allIcons as any;
  routeData = [];
  newRoute.map(item => {
    const { icon, children, name, path } = item;

    // 渲染主菜单图标
    if (icon) {
      const iconName = icon[0].toUpperCase() + icon.substring(1) + "Outlined";
      item.icon = createElement(icons[iconName]);
    }

    // 渲染路由结点 element
    // 通常 lazy 和 Suspense 搭配使用。
    if (children) {
      children.map(child => {
        const { element, name } = child;
        mappingPath[element] = name;
        const Page = lazy(() => import("./pages/" + element));
        child.element = <Suspense><Page /></Suspense>;
      });
    } else {
      mappingPath[path] = name;
      const Page = lazy(() => import("./pages/" + path));
      item.element = <Suspense><Page /></Suspense>;
    }

    routeData.push(item);
    // if (routeData.length === newRoute.length) oldRender();
  });
  oldRender();
};

export const request: RequestConfig = {
  timeout: 1000 * 10, // 秒
  baseURL: apiUrl + "api/",
  errorConfig: {
    errorHandler: (e: any) => {
      if (e.response && e.response.status !== 200)
        message.error("网络连接发生错误");
      else if (e.request)
        message.error("网络连接超时");
    },
  },
  requestInterceptors: [
    (url: string, options: RequestConfig) => {
      const { headers = {} } = options;
      if (url === loginPath.substring(1)) return { url, options };

      const { token, user } = storage.getData();
      if (token.length !== 14) {
        history.replace({ pathname: loginPath });
        throw new Error("访问令牌不正确：" + token); // 阻止此次网络请求
      } else headers["k"] = decode(token) + "=" + user.id;
      if (url.includes('/upload'))
        options.timeout = 1000 * 10 * 3; // 在调用上传接口时，设置更长的超时时长。
      return { url, options };
    },
  ],
  responseInterceptors: [
    (res: any) => {
      const { skipErrorHandler } = res.config;
      if (skipErrorHandler) return res; // 跳过异常处理

      const data: TYPE.Response = res.data;
      const { success, msg } = data;
      if (success) return res;

      if (msg) message.error(msg);
      throw new Error(msg); // 阻止业务逻辑往下执行
    },
  ],
};
